package com.jiahe.blog.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jiahe.blog.dao.MenuDao;
import com.jiahe.blog.entity.MenuEntity;
import com.jiahe.blog.model.BlogConst;
import com.jiahe.blog.model.dto.LabelOptionDTO;
import com.jiahe.blog.model.dto.MenuDTO;
import com.jiahe.blog.model.dto.UserMenuDTO;
import com.jiahe.blog.model.vo.ConditionVO;
import com.jiahe.blog.service.MenuService;
import com.jiahe.blog.utils.BeanCopyUtils;
import com.jiahe.blog.utils.StringUtils;
import com.jiahe.blog.utils.UserUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class MenuServiceImpl extends ServiceImpl<MenuDao, MenuEntity> implements MenuService {

    @Autowired
    private MenuDao menuDao;

    @Override
    public List<MenuDTO> listMenus(ConditionVO conditionVO) {
        // 获取查询的关键词
        String keywords = conditionVO.getKeywords();
        // 查询菜单数据
        List<MenuEntity> menuEntityList = this.list(new LambdaQueryWrapper<MenuEntity>()
                .like(StringUtils.isNotBlank(keywords), MenuEntity::getName, keywords));
        // 获取一级菜单列表
        List<MenuEntity> catalogList = listCatalog(menuEntityList);
        // 获取一级菜单下的子菜单
        Map<Integer, List<MenuEntity>> childrenMap = getChildrenMap(menuEntityList);
        // 组装目录菜单数据
        return catalogList.stream()
                .map(item -> {
                    MenuDTO menuDTO = BeanCopyUtils.copyObject(item, MenuDTO.class);
                    // 获取目录下的菜单排序
                    List<MenuDTO> list = BeanCopyUtils.copyList(childrenMap.get(item.getId()), MenuDTO.class).stream()
                            .sorted(Comparator.comparing(MenuDTO::getOrderNum))
                            .collect(Collectors.toList());
                    menuDTO.setChildren(list);
                    return menuDTO;
                }).sorted(Comparator.comparing(MenuDTO::getOrderNum)).collect(Collectors.toList());
    }

    @Override
    public List<LabelOptionDTO> listMenuOptions() {
        // 查询菜单数据
        List<MenuEntity> list = this.list(new LambdaQueryWrapper<MenuEntity>()
                .select(MenuEntity::getId, MenuEntity::getName, MenuEntity::getParentId, MenuEntity::getOrderNum));
        // 获取目录列表
        List<MenuEntity> catalog = listCatalog(list);
        // 获取目录下的子菜单
        Map<Integer, List<MenuEntity>> childrenMap = getChildrenMap(list);
        // 组装目录菜单数据
        return catalog.stream().map(item -> {
            // 获取目录下的菜单排序
            List<LabelOptionDTO> labelOptionDTOList = new ArrayList<>();
            List<MenuEntity> children = childrenMap.get(item.getId());
            if (CollectionUtils.isNotEmpty(children)) {
                labelOptionDTOList = children.stream()
                        .sorted(Comparator.comparing(MenuEntity::getOrderNum))
                        .map(menu -> LabelOptionDTO.builder()
                                .id(menu.getId())
                                .label(menu.getName())
                                .build())
                        .collect(Collectors.toList());
            }
            return LabelOptionDTO.builder()
                    .id(item.getId())
                    .label(item.getName())
                    .children(labelOptionDTOList)
                    .build();
        }).collect(Collectors.toList());
    }

    @Override
    public List<UserMenuDTO> listUserMenus() {
        // 查询用户菜单数据
        List<MenuEntity> userMenuList = menuDao.listMenusByUserInfoId(UserUtils.getLoginUser().getUserInfoId());
        // 获取目录列表
        List<MenuEntity> catalogList = listCatalog(userMenuList);
        // 获取目录下的子菜单
        Map<Integer, List<MenuEntity>> childrenMap = getChildrenMap(userMenuList);
        //转换前端菜单格式
        return convertUserMenuList(catalogList,childrenMap);
    }

    /**
     * 获取一级菜单列表
     *
     * @param menuList 菜单列表
     * @return 目录列表
     */
    private List<MenuEntity> listCatalog(List<MenuEntity> menuList) {
        return menuList.stream()
                .filter(item -> Objects.isNull(item.getParentId()))
                .sorted(Comparator.comparing(MenuEntity::getOrderNum))
                .collect(Collectors.toList());
    }

    /**
     * 获取子菜单
     * @param menuList 菜单列表
     * @return 目录下的菜单列表
     */
    private Map<Integer, List<MenuEntity>> getChildrenMap(List<MenuEntity> menuList) {
        return menuList.stream()
                .filter(item -> Objects.nonNull(item.getParentId()))
                .collect(Collectors.groupingBy(MenuEntity::getParentId));
    }

    /**
     * 转换用户菜单格式
     *
     * @param catalogList 目录
     * @param childrenMap 子菜单
     */
    private List<UserMenuDTO> convertUserMenuList(List<MenuEntity> catalogList, Map<Integer, List<MenuEntity>> childrenMap) {
        return catalogList.stream().map(item -> {
            // 获取目录
            UserMenuDTO userMenuDTO = new UserMenuDTO();
            List<UserMenuDTO> list = new ArrayList<>();
            // 获取目录下的子菜单
            List<MenuEntity> children = childrenMap.get(item.getId());
            if (CollectionUtils.isNotEmpty(children)) {
                // 多级菜单处理
                userMenuDTO = BeanCopyUtils.copyObject(item, UserMenuDTO.class);
                list = children.stream()
                        .sorted(Comparator.comparing(MenuEntity::getOrderNum))
                        .map(menuEntity -> {
                            UserMenuDTO dto = BeanCopyUtils.copyObject(menuEntity, UserMenuDTO.class);
                            dto.setHidden(menuEntity.getHidden().equals(BlogConst.TURE));
                            return dto;
                        }).collect(Collectors.toList());
            } else {
                // 一级菜单处理
                userMenuDTO.setPath(item.getPath());
                userMenuDTO.setComponent(BlogConst.COMPONENT);
                list.add(UserMenuDTO.builder()
                        .path("")
                        .name(item.getName())
                        .icon(item.getIcon())
                        .component(item.getComponent()).build());
            }
            userMenuDTO.setHidden(item.getHidden().equals(BlogConst.TURE));
            userMenuDTO.setChildren(list);
            return userMenuDTO;
        }).collect(Collectors.toList());
    }
}
